﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace paddle_ocrlabel
{
    public partial class Form5 : Form
    {
        String pre_url = @"http://127.0.0.1:5000/";

        bool isDirty = false;

        String imageFolderPath = "";

        float fScale = 1.0f;
        Point start; //画框的起始点
        bool blnDraw;//判断是否绘制

        //用来放当前页面的自标注
        List<PaddleEntity> allRectList = new List<PaddleEntity>();

        Rectangle newRect;
        String cachePath = null;

        String currentFullImagePath = null;
        float currentImageRate = 1.0f;
        Image currentImage = null;

        private CancellationTokenSource _Cts; //任务取消令牌;
        private AutoResetEvent _AutoResetEvent = new AutoResetEvent(false);//参数传 false，则 WaitOne 时阻塞等待;

        public Form5()
        {
            InitializeComponent();
        }



        private void btnAutoLabel_Click(object sender, EventArgs e)
        {
            if (lbImages.Items.Count == 0)
            {
                MessageBox.Show("请先选择要标注的图片目录！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List<string> orders = new List<string>() { }; //业务数据;

            foreach (var item in lbImages.Items)
            {
                orders.Add(item.ToString());
            }

            string businessName = "标注";

            String url = null;
            AsyncCallback callback = null;
            if (rboDetect.Checked)
            {
                url = pre_url + "detect";
                callback = DetectCompleate;
            }
            else
            {
                url = pre_url + "recognition";
                callback = RecognitionCompleate;
            }

            Dictionary<String, String> dicParams = new Dictionary<string, string>();
            ShowDialog(businessName, orders, url, dicParams, callback);
        }

        void ShowDialog(string businessName, List<String> orders, String url, Dictionary<String, String> dicParams, AsyncCallback callback)
        {
            FormProgressDialog progressWindow = new FormProgressDialog();
            progressWindow.Text = "任务处理窗口";

            progressWindow.SetColorfulTitle(businessName, Color.DarkOrange, true);
            progressWindow.SetColorfulTitle("正在执行中......", Color.Black);
            progressWindow.SetInfo(null, "", "");

            List<string> leftList = orders.Select(x => x).ToList(); //剩余（未处理）数据;
            int successCount = 0; //成功数量;

            _Cts = new CancellationTokenSource();

            //注册一个将在取消此 CancellationToken 时调用的委托;
            _Cts.Token.Register(async () =>
            {
                ShowInfo("操作终止");

                await Task.Run(() =>
                {
                    _AutoResetEvent.WaitOne(1000 * 5); //等待有可能还在执行的业务方法;

                    if (successCount < orders.Count)
                    {
                        ShowInfo($"{businessName} 有 {orders.Count - successCount} 项任务被终止，可在消息框中查看具体项。");

                        foreach (var leftName in leftList)
                        {
                            ShowInfo($"【{businessName}】的【{leftName}】执行失败，失败原因：【手动终止】。");
                        }
                    }
                });
            });

            progressWindow.OperateAction += () =>
            {
                Task task = new Task(() =>
                {
                    foreach (var order in orders)
                    {
                        //判断是否被取消;
                        if (_Cts.Token.IsCancellationRequested)
                        {
                            break;
                        }

                        progressWindow.BeginInvoke(new Action(() =>
                        {
                            progressWindow.SetInfo(null, $"共{orders.Count}项，已执行{successCount}项", $"当前正在执行：{order}");
                        }));

                                               
                        dicParams["image_path"] = imageFolderPath + order;

                        if (invokeNetwork(order, url, dicParams, callback))
                        {
                            successCount++;
                            leftList.RemoveAll(x => x == order);

                            if (_Cts.Token.IsCancellationRequested)
                            {
                                _AutoResetEvent.Set(); //放行 Register 委托处的等待;
                            }
                        }

                        try
                        {
                            progressWindow.BeginInvoke(new Action(() =>
                            {
                                progressWindow.SetProsess(orders.IndexOf(order) + 1, orders.Count);
                            }));
                        }
                        catch (Exception ex)
                        {

                        }
                    }

                    //正常结束则延迟一段时间来让进度条走完;
                    if (!_Cts.Token.IsCancellationRequested)
                    {
                        Thread.Sleep(200);
                    }
                }, _Cts.Token);

                task.Start();
                task.Wait();
            };

            progressWindow.AbortAction += () =>
            {
                _Cts.Cancel();
            };

            var result = progressWindow.ShowDialog();
            int leftCount = orders.Count - successCount;
            if (result == DialogResult.OK || leftCount <= 0)
            {
                ShowInfo($"{businessName} 整体完成。");
            }
            else if (result == DialogResult.Abort)
            {
                //移到 _Cts.Token.Register 处一起判断，不然数目可能不准;
                //ShowInfo($"{businessName} 有 {leftCount} 项任务被终止，可在消息框中查看具体项。");
            }
        }

        private bool invokeNetwork(string order, String url, Dictionary<String, String> dicParams, AsyncCallback callback)
        {
            string errStr = $"{order} 识别失败，失败原因：";

            NetAsync(url, dicParams, callback);

            try
            {
                //业务方法;
                ShowInfo($"【{order}】的 {order} 任务执行成功。");
                return true;
            }
            catch (Exception ex)
            {
                ShowInfo($"{errStr}{ex.Message}");
            }

            return false;
        }

        public static string HttpPostSync(string url)
        {
            string result = "";

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.ContentType = "text/json";
            req.Method = "POST";
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();
 
            //获取内容  
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                result = reader.ReadToEnd();
            }

            return result;
        }

        public void NetAsync(string url, Dictionary<String, String> dicParams, AsyncCallback callback)
        {           
            try
            {
                StringBuilder sb = new StringBuilder();
                foreach (var key in dicParams.Keys)
                {
                    sb.Append(key + "=" + dicParams[key] + "&");
                }

                var str = sb.ToString();
                string postData = str.Substring(0, str.Length -1);
                byte[] data = Encoding.UTF8.GetBytes(postData);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";


                request.ContentLength = data.Length;
                Stream newStream = request.GetRequestStream();

                // Send the data.
                newStream.Write(data, 0, data.Length);
                newStream.Close();


                NetworkParams networkParams = new NetworkParams()
                {
                    request = request,
                    fileFullPath = dicParams["image_path"]
                };

                request.BeginGetResponse(callback, networkParams);
            }
            catch
            {
                Console.WriteLine(DateTime.Now.ToString("hh:mm:ss") + " 识别失败");
            }
        }

        class NetworkParams
        {
            public HttpWebRequest request { get; set; }
            public String fileFullPath { get; set; }
        }

        public void DetectCompleate(IAsyncResult asyncResult)
        {
            try
            {
                NetworkParams networkParams = (asyncResult.AsyncState as NetworkParams); 
                HttpWebRequest req = networkParams.request;
                String imageFullPath = networkParams.fileFullPath;
                String encode = FileUtils.UrlEncode(imageFullPath);

                HttpWebResponse res = req.EndGetResponse(asyncResult) as HttpWebResponse;

                //获取内容  
                String content = null;
                using (StreamReader reader = new StreamReader(res.GetResponseStream(), Encoding.UTF8))
                {
                    content = reader.ReadToEnd();
                }

                var result = JSONUtils.Json2Obj<PaddleOCR>(content);
                List<PaddleEntity> ocrList = null;
                if (rboFromTop.Checked)
                {
                    ocrList = result.paddle_result.OrderBy(x => x.top).ThenByDescending(x => x.left).ToList() ;
                }
                else
                {
                    ocrList = result.paddle_result.OrderByDescending(x => x.left).ThenBy(x => x.top).ToList() ;
                }

                FileStream fs = new FileStream(cachePath + encode + ".json", FileMode.Create);
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
                sw.WriteLine(content);
                sw.Close();
                fs.Close();

                this.BeginInvoke((System.Action)(() =>
                {
                    if (imageFullPath == currentFullImagePath)
                    {
                        tvResults.Nodes.Clear();

                        foreach (var item in ocrList)
                        {
                            TreeNode node = new TreeNode(item.ToString());
                            node.Tag = item.ToString();
                            tvResults.Nodes.Add(node);

                            allRectList.Add(new PaddleEntity() {
                                left = item.left,
                                top = item.top,
                                width = item.width,
                                height = item.height,
                                isNew = false,
                            });
                        }

                        picPreview.Invalidate();
                        tvResults.ExpandAll();
                    }
                }));
            }
            catch(Exception ex)
            {
                Console.WriteLine(DateTime.Now.ToString("hh:mm:ss") + ex.Message);
            }
        }

        public void RecognitionCompleate(IAsyncResult asyncResult)
        {
            try
            {
                NetworkParams networkParams = (asyncResult.AsyncState as NetworkParams);
                HttpWebRequest req = networkParams.request;
                String imageFullPath = networkParams.fileFullPath;
                String encode = FileUtils.UrlEncode(imageFullPath);

                HttpWebResponse res = req.EndGetResponse(asyncResult) as HttpWebResponse;

                //获取内容  
                String content = null;
                using (StreamReader reader = new StreamReader(res.GetResponseStream(), Encoding.UTF8))
                {
                    content = reader.ReadToEnd();
                }                

                FileStream fs = new FileStream(cachePath + encode + ".json", FileMode.Create);
                StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
                sw.WriteLine(content);
                sw.Close();
                fs.Close();

                var result = JSONUtils.Json2Obj<PaddleOCR>(content);
                List<PaddleEntity> ocrList = null;
                if (rboFromTop.Checked)
                {
                    ocrList = result.paddle_result.OrderBy(x => x.top).ThenByDescending(x => x.left).ToList();
                }
                else
                {
                    ocrList = result.paddle_result.OrderByDescending(x => x.left).ThenBy(x => x.top).ToList();
                }

                this.BeginInvoke((System.Action)(() =>
                {
                    if (imageFullPath == currentFullImagePath)
                    {
                        tvResults.Nodes.Clear();

                        foreach (var item in ocrList)
                        {
                            TreeNode node = new TreeNode(item.ToString());
                            node.Tag = item.ToString();
                            TreeNode subNode = new TreeNode(item.text);
                            node.Nodes.Add(subNode);
                            tvResults.Nodes.Add(node);

                            allRectList.Add(new PaddleEntity()
                            {
                                left = item.left,
                                top = item.top,
                                width = item.width,
                                height = item.height,
                                text = item.text,
                                isNew = false,
                            });
                        }

                        picPreview.Invalidate();
                        tvResults.ExpandAll();
                    }
                }));
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now.ToString("hh:mm:ss") + ex.Message);
            }
        }

        public void RegregionCompleate(IAsyncResult asyncResult)
        {
            try
            {
                NetworkParams networkParams = (asyncResult.AsyncState as NetworkParams);
                HttpWebRequest req = networkParams.request;
                String imageFullPath = networkParams.fileFullPath;
                String encode = FileUtils.UrlEncode(imageFullPath);

                HttpWebResponse res = req.EndGetResponse(asyncResult) as HttpWebResponse;

                //获取内容  
                String content = null;
                using (StreamReader reader = new StreamReader(res.GetResponseStream(), Encoding.UTF8))
                {
                    content = reader.ReadToEnd();
                }               

                var result = JSONUtils.Json2Obj<PaddleEntity>(content);

                this.BeginInvoke((System.Action)(() =>
                {
                    if (tvResults.SelectedNode.Nodes.Count == 0)
                    {
                        tvResults.SelectedNode.Nodes.Add(result.text);
                    }
                    else
                    {
                        tvResults.SelectedNode.Nodes[0].Text = result.text;
                    }

                    isDirty = true;
                }));
            }
            catch (Exception ex)
            {
                Console.WriteLine(DateTime.Now.ToString("hh:mm:ss") + ex.Message);
            }
        }        

        private void lbImages_MouseCaptureChanged(object sender, EventArgs e)
        {
            String imagePath = imageFolderPath + lbImages.Text;
            if (currentFullImagePath == imagePath || lbImages.Items.Count == 0)
                return;

            if (isDirty)
            {
                if (MessageBox.Show("当前图片标注已修改，要保存吗？", "警告", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    btnSave_Click(null, null);
                }

                isDirty = false;
            }

            if(currentImage!=null)
            {
                currentImage.Dispose();
            }            
            
            Image bmp = Image.FromFile(imagePath);
            currentImage = bmp;

            currentImageRate = bmp.Height / (bmp.Width + 0.0f);
            float pbRate = groupBox2.Height / (groupBox2.Width + 0.0f);
            if (pbRate > currentImageRate)
            {
                fScale = groupBox2.Width / (bmp.Width + 0.0f);
            } else
            {
                fScale = groupBox2.Height / (bmp.Height + 0.0f);
            }            

            picPreview.Image = new Bitmap(bmp, Convert.ToInt32(bmp.Width * fScale), Convert.ToInt32(bmp.Height * fScale));

            showBiaozhu(imagePath);

            currentFullImagePath = imagePath;
        }

        void showBiaozhu(String imagePath)
        {
            tvResults.Nodes.Clear();
            allRectList.Clear();

            picPreview.Invalidate();

            String cacheFileName = FileUtils.UrlEncode(imagePath) + ".json";
            if (!File.Exists(cachePath + cacheFileName))
                return;

            //获取内容  
            String content = null;
            using (StreamReader reader = new StreamReader(cachePath + cacheFileName, Encoding.UTF8))
            {
                content = reader.ReadToEnd();
            }

            var result = JSONUtils.Json2Obj<PaddleOCR>(content);
            List<PaddleEntity> ocrList = null;
            if (rboFromTop.Checked)
            {
                ocrList = result.paddle_result.OrderBy(x => x.top).ThenByDescending(x => x.left).ToList();
            }
            else
            {
                ocrList = result.paddle_result.OrderByDescending(x => x.left).ThenBy(x => x.top).ToList();
            }

            foreach (var item in ocrList)
            {
                TreeNode node = new TreeNode(item.ToString());
                tvResults.Nodes.Add(node);

                if (rboRec.Checked)
                {
                    node.Nodes.Add(item.text);
                }

                allRectList.Add(new PaddleEntity()
                {
                    left = item.left,
                    top = item.top,
                    width = item.width,
                    height = item.height,
                    text = item.text,
                    isNew = false,
                });
            }

            tvResults.ExpandAll();
            picPreview.Invalidate();
        }

        private void Form5_Resize(object sender, EventArgs e)
        {
            if (currentFullImagePath != null)
            {
                if (groupBox2.Width == 0 || groupBox2.Height == 0)
                    return;

                float pbRate = groupBox2.Height / (groupBox2.Width + 0.0f);
                if (pbRate > currentImageRate)
                {
                    fScale = groupBox2.Width / (currentImage.Width + 0.0f);
                }
                else
                {
                    fScale = groupBox2.Height / (currentImage.Height + 0.0f);
                }

                picPreview.Image = new Bitmap(currentImage, Convert.ToInt32(currentImage.Width * fScale), Convert.ToInt32(currentImage.Height * fScale));                
            }
        }

        private void picPreview_MouseDown(object sender, MouseEventArgs e)
        {
            if(currentImage!= null)
            {
                float safeWidth = currentImage.Width * fScale;
                float safeHeight = currentImage.Height * fScale;

                if (e.X > safeWidth || e.Y > safeHeight)
                    return;
            }

            start = e.Location;
            blnDraw = true;
        }

        private void picPreview_MouseMove(object sender, MouseEventArgs e)
        {
            if (blnDraw && currentImage!=null && btnRectLabel.Tag.ToString() == "0")
            {
                if (e.Button != MouseButtons.Left)//判断是否按下左键
                    return;

                float safeWidth = currentImage.Width * fScale;
                float safeHeight = currentImage.Height * fScale;

                Point tempEndPoint = e.Location; //记录框的位置和大小
                if(e.X > safeWidth)
                {
                    tempEndPoint.X = Convert.ToInt32(safeWidth);
                }

                if (e.Y > safeHeight)
                {
                    tempEndPoint.Y = Convert.ToInt32(safeHeight);
                }

                newRect = new Rectangle();
                newRect.Location = new Point(
                    Math.Min(start.X, tempEndPoint.X),
                    Math.Min(start.Y, tempEndPoint.Y));
                newRect.Size = new Size(
                    Math.Abs(start.X - tempEndPoint.X),
                    Math.Abs(start.Y - tempEndPoint.Y));                               

                picPreview.Invalidate();
            }
        }

        private void picPreview_MouseUp(object sender, MouseEventArgs e)
        {
            blnDraw = false; //结束绘制

            if (picPreview.Image != null && btnRectLabel.Tag.ToString() == "0")
            {
                if (newRect != null && newRect.Width > 0 && newRect.Height > 0)
                {
                    var entity = new PaddleEntity()
                    {
                        left = Convert.ToInt32(newRect.Left / fScale),
                        top = Convert.ToInt32(newRect.Top / fScale),
                        width = Convert.ToInt32(newRect.Width / fScale),
                        height = Convert.ToInt32(newRect.Height / fScale)
                    };

                    TreeNode node = new TreeNode(entity.ToString());
                    node.Tag = entity.ToString();
                    tvResults.Nodes.Add(node);

                    allRectList.Add(new PaddleEntity()
                    {
                        left = Convert.ToInt32(newRect.X / fScale),
                        top = Convert.ToInt32(newRect.Y / fScale),
                        width = Convert.ToInt32(newRect.Width / fScale),
                        height = Convert.ToInt32(newRect.Height / fScale),
                        isNew = true,
                    });

                    isDirty = true;

                    newRect = new Rectangle();
                }     
            }
        }

        private void picPreview_Paint(object sender, PaintEventArgs e)
        {
            if (currentImage != null)
            {
                int safeWidth = Convert.ToInt32(currentImage.Width * fScale);
                int safeHeight = Convert.ToInt32(currentImage.Height * fScale);

                Pen pen = new Pen(Color.Gray, 1);
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
                pen.DashPattern = new float[] { 5, 5 };
                e.Graphics.DrawRectangle(pen, 0, 0, safeWidth, safeHeight);
            }

            foreach (var rect in allRectList)
            {
                Color color = Color.Blue;

                if (rect.isSelected)
                {
                    color = Color.Red;
                } else
                {
                    if(rect.isNew)
                    {
                        color = Color.Orange;
                    }
                }

                Rectangle newRect1 = new Rectangle()
                {
                    X = Convert.ToInt32(rect.left * fScale),
                    Y = Convert.ToInt32(rect.top * fScale),
                    Width = Convert.ToInt32(rect.width * fScale),
                    Height = Convert.ToInt32(rect.height * fScale),
                };
                e.Graphics.DrawRectangle(new Pen(color, 2), newRect1);
            }

            if (blnDraw)
            {
                if (newRect != null && newRect.Width > 0 && newRect.Height > 0)
                {
                    e.Graphics.DrawRectangle(new Pen(Color.Orange, 2), newRect);
                }
            }
        }

        private void btnSingleLabel_Click(object sender, EventArgs e)
        {
            String image_path = imageFolderPath + lbImages.Text;

            if (lbImages.Items.Count == 0)
            {
                MessageBox.Show("请先选择要标注的图片目录！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (lbImages.Text == "")
            {
                MessageBox.Show("请先选择要标注的图片！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List<string> orders = new List<string>() { lbImages.Text }; //业务数据;

            string businessName = "标注";

            String url = null;
            AsyncCallback callback = null;
            if (rboDetect.Checked)
            {
                url = pre_url + "detect";
                callback = DetectCompleate;
            }
            else
            {
                url = pre_url + "recognition";
                callback = RecognitionCompleate;
            }

            Dictionary<String, String> dicParams = new Dictionary<string, string>();
            ShowDialog(businessName, orders, url, dicParams, callback);
        }

        private void ShowInfo(string messgae)
        {
            //TBMessage.TryBeginInvoke(new Action(() =>
            //{
            //    TBMessage.AppendText($"{messgae}\r\n\r\n");
            //}));
        }

        private void menu51_Click(object sender, EventArgs e)
        {

        }

        private void Form5_Load(object sender, EventArgs e)
        {
            var cacheDetectPath = System.Environment.CurrentDirectory + @"\Cache\Detect\";
            var cacheRecPath = System.Environment.CurrentDirectory + @"\Cache\Rec\";
            FileUtils.createDirectory(cacheDetectPath);
            FileUtils.createDirectory(cacheRecPath);

            cachePath = cacheDetectPath;
        }

        private void rboDetect_CheckedChanged(object sender, EventArgs e)
        {
            if(rboDetect.Checked)
            {
                cachePath = System.Environment.CurrentDirectory + @"\Cache\Detect\";
            } else
            {
                cachePath = System.Environment.CurrentDirectory + @"\Cache\Rec\";
            }

            if (isDirty)
            {
                if (MessageBox.Show("当前图片标注已修改，要保存吗？", "警告", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    btnSave_Click(null, null);
                }

                isDirty = false;
            }

            if (currentImage != null)
            {
                String imagePath = imageFolderPath + lbImages.Text;
                showBiaozhu(imagePath);
            }
        }        

        private void btnOCRAgain_Click(object sender, EventArgs e)
        {
            if (rboDetect.Checked)
            {
                MessageBox.Show("该功能只有在开启了左上角的识别模式后才能生使用！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (tvResults.Nodes.Count == 0)
                return;

            if (tvResults.SelectedNode == null)
            {
                MessageBox.Show("请先选择下面的一个区域！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            String strRegion = null;

            //选中的是坐标节点
            if (tvResults.SelectedNode.Parent == null)
            {
                strRegion = tvResults.SelectedNode.Text;
            } else //选中的是文本
            {
                strRegion = tvResults.SelectedNode.Parent.Text;
            }

            string[] arrRegion = strRegion.Split(new char[2] { ':', ',' });

            List<string> orders = new List<string>() { }; //业务数据;

            foreach (var item in lbImages.Items)
            {
                orders.Add(item.ToString());
            }

            string businessName = "标注某个区域";

            Dictionary<String, String> dicParams = new Dictionary<string, string>();
            dicParams["left"] = arrRegion[1];
            dicParams["top"] = arrRegion[3];
            dicParams["width"] = arrRegion[5];
            dicParams["height"] = arrRegion[7];
            var url = pre_url + "regregion";

            ShowDialog(businessName, new List<String>{lbImages.Text}, url, dicParams, RegregionCompleate);
        }

        private void btnRectLabel_Click(object sender, EventArgs e)
        {
            if (currentImage == null)
                return;

            //0为正在标注，1为关闭标注
            if (btnRectLabel.Tag.ToString() == "1")
            {
                btnRectLabel.Text = "停止矩阵标注";
                btnRectLabel.Tag = "0";
            }
            else
            {
                btnRectLabel.Text = "启动矩形标注";
                btnRectLabel.Tag = "1";
            }
        }

        private void tvResults_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if(e.Node.Parent != null)
            {
                return;
            }

            string[] arrRegion = e.Node.Text.Split(new char[2] { ':', ',' });
            var left = int.Parse(arrRegion[1]);
            var top = int.Parse(arrRegion[3]);
            var width = int.Parse(arrRegion[5]);
            var height = int.Parse(arrRegion[7]);            

            foreach (var item in allRectList)
            {
                if(item.isSelected)
                {
                    item.isSelected = false;
                    continue;
                }

                if (item.left == left && item.top == top && item.width == width && item.height == height)
                {
                    item.isSelected = true;
                    continue;
                }
            }

            picPreview.Invalidate();
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if(currentFullImagePath== null || currentFullImagePath=="")
                return;

            List<PaddleEntity> list = new List<PaddleEntity>();

            //没有text，则存为null
            foreach (var item in allRectList)
            {
                list.Add(new PaddleEntity()
                {
                    left = item.left,
                    top = item.top,
                    width = item.width,
                    height = item.height,
                    text = item.text
                });
            }

            PaddleOCR paddleOCR = new PaddleOCR() { paddle_result = list };

            var content = JSONUtils.Obj2Json(paddleOCR);
          
            String encode = FileUtils.UrlEncode(currentFullImagePath);
            FileStream fs = new FileStream(cachePath + encode + ".json", FileMode.Create);
            StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
            sw.WriteLine(content);
            sw.Close();
            fs.Close();

            isDirty = false;
        }

        private void btnRollBack_Click(object sender, EventArgs e)
        {
            if(allRectList.Count == 0 || !allRectList[allRectList.Count - 1].isNew)
            {
                return;
            }

            allRectList.RemoveAt(allRectList.Count - 1);
            tvResults.Nodes.RemoveAt(tvResults.Nodes.Count-1);
            picPreview.Invalidate();
        }

        private void Form5_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.S && e.Control)
            {
                btnSave_Click(null, null);
            } else if (e.KeyCode == Keys.Z && e.Control)
            {
                btnRollBack_Click(null, null);
            }
        }

        private void rboFromTop_CheckedChanged(object sender, EventArgs e)
        {
            tvResults.Nodes.Clear();

            List<PaddleEntity> newList = null;

            if (rboFromTop.Checked)
            {
                newList = allRectList.OrderBy(x => x.top).ThenByDescending(x => x.left).ToList();
            }
            else
            {
                newList = allRectList.OrderByDescending(x => x.left).ThenBy(x => x.top).ToList();
            }

            foreach (var item in newList)
            {
                TreeNode node = new TreeNode(item.ToString());
                node.Tag = item.ToString();
                tvResults.Nodes.Add(node);
            }
        }

        private void btnChooseImageFoloder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();

            if (dialog.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }

            lbImages.Items.Clear();
            imageFolderPath = dialog.DirectoryPath + @"\";

            DirectoryInfo root = new DirectoryInfo(imageFolderPath);
            foreach (FileInfo f in root.GetFiles())
            {
                if (f.Extension.Contains("jpg") || f.Extension.Contains("jpeg") || f.Extension.Contains("png"))
                {
                    lbImages.Items.Add(f.Name);
                }
            }

            lblImageFolderPath.Text = imageFolderPath;

            tvResults.Nodes.Clear();
            allRectList.Clear();

            currentImage = null;
            currentFullImagePath = null;
            currentImageRate = 1.0f;
        }
       
    }
}
